package cn.harry.cabinet.utils

import android.content.Context
import android.util.Log
import cn.harry.cabinet.constants.OperationLogConstants
import cn.harry.cabinet.model.entity.OperationLog
import cn.harry.cabinet.repository.OperationLogRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

/**
 * 操作日志扩展函数
 * 提供简洁的日志记录方式
 * 
 * 注意：所有日志记录均为异步操作，在 IO 线程中执行，不会阻塞主线程或影响业务逻辑
 */

/**
 * 快速记录配置修改日志
 * 
 * @param scope 协程作用域，通常使用 viewLifecycleOwner.lifecycleScope
 * @param subType 操作子类型，如 SERVER_CONTROL、EXTERNAL_API_CONFIG 等
 * @param description 操作描述
 * @param oldValue 修改前的值（可选）
 * @param newValue 修改后的值（可选）
 * 
 * 该函数是异步的，使用 Dispatchers.IO 在后台线程执行，不会阻塞调用线程
 * 即使日志记录失败，也不会影响业务逻辑的执行
 */
fun Context.logConfigChange(
    scope: CoroutineScope,
    subType: String,
    description: String,
    oldValue: String? = null,
    newValue: String? = null
) {
    // 使用 IO 调度器在后台线程异步执行，避免阻塞主线程
    scope.launch(Dispatchers.IO) {
        try {
            val detailData = if (oldValue != null && newValue != null) {
                "修改前: $oldValue\n修改后: $newValue"
            } else null
            
            val timestamp = System.currentTimeMillis()
            val log = OperationLog(
                operationType = OperationLogConstants.OperationType.CONFIG_CHANGE,
                operationSubType = subType,
                result = OperationLogConstants.Result.SUCCESS,
                description = description,
                targetType = OperationLogConstants.TargetType.CONFIG,
                targetName = subType,
                detailData = detailData,
                timestamp = timestamp
            )
            
            // 打印 Debug 日志到控制台
            printDebugLog(subType, description, oldValue, newValue, timestamp)
            
            val repository = OperationLogRepository(applicationContext as android.app.Application)
            repository.insert(log)
            
            // 记录成功后打印确认信息
            Log.d("OperationLogExt", "✅ 日志已保存到数据库")
        } catch (e: Exception) {
            // 日志记录失败不影响业务逻辑，仅记录错误信息
            Log.e("OperationLogExt", "❌ 记录日志失败: ${e.message}", e)
        }
    }
}

/**
 * 打印 Debug 日志到控制台
 */
private fun printDebugLog(
    subType: String,
    description: String,
    oldValue: String?,
    newValue: String?,
    timestamp: Long
) {
    val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault())
    val timeStr = dateFormat.format(Date(timestamp))
    
    val logMessage = buildString {
        appendLine("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
        appendLine(" 操作日志记录")
        appendLine("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
        appendLine(" 时间: $timeStr")
        appendLine(" 类型: CONFIG_CHANGE")
        appendLine(" 子类型: $subType")
        appendLine(" 描述: $description")
        if (oldValue != null) {
            appendLine("🔹 旧值: $oldValue")
        }
        if (newValue != null) {
            appendLine("🔸 新值: $newValue")
        }
        append("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
    }
    
    Log.d("OperationLog", logMessage)
}

/**
 * 快速记录主题切换日志
 */
fun Context.logThemeChange(
    scope: CoroutineScope,
    oldTheme: String,
    newTheme: String
) {
    logConfigChange(
        scope = scope,
        subType = OperationLogConstants.OperationSubType.THEME_CHANGE,
        description = "切换主题: $oldTheme → $newTheme",
        oldValue = oldTheme,
        newValue = newTheme
    )
}

/**
 * 记录人脸识别日志
 * 
 * @param scope 协程作用域
 * @param result 结果：SUCCESS 或 FAILED
 * @param description 操作描述
 * @param userId 用户ID（可选）
 * @param employeeId 工号（可选）
 * @param userName 用户名（可选）
 * @param errorMessage 错误信息（可选）
 * @param detailData 详细数据（可选）
 */
fun Context.logFaceRecognition(
    scope: CoroutineScope,
    result: String,
    description: String,
    userId: Long? = null,
    employeeId: String? = null,
    userName: String? = null,
    errorMessage: String? = null,
    detailData: Map<String, Any>? = null
) {
    scope.launch(Dispatchers.IO) {
        try {
            val log = OperationLog(
                operationType = OperationLogConstants.OperationType.USER_AUTH,
                operationSubType = "FACE_RECOGNITION",
                result = result,
                description = description,
                operatorId = userId,
                operatorEmployeeId = employeeId,
                operatorName = userName,
                errorMessage = errorMessage,
                detailData = detailData?.let { org.json.JSONObject(it).toString() },
                timestamp = System.currentTimeMillis()
            )
            
            val repository = OperationLogRepository(applicationContext as android.app.Application)
            repository.insert(log)
            
            Log.d("OperationLogExt", "✅ 人脸识别日志已保存: $description")
        } catch (e: Exception) {
            Log.e("OperationLogExt", "❌ 记录人脸识别日志失败: ${e.message}", e)
        }
    }
}

/**
 * 记录刷卡操作日志（取出/归还）
 * 
 * @param scope 协程作用域
 * @param operationType 操作类型：INSTRUMENT_TAKE 或 INSTRUMENT_RETURN
 * @param result 结果：SUCCESS 或 FAILED
 * @param description 操作描述
 * @param cardNumber 卡号
 * @param userId 用户ID（可选）
 * @param employeeId 工号（可选）
 * @param userName 用户名（可选）
 * @param errorMessage 错误信息（可选）
 * @param detailData 详细数据（可选）
 */
fun Context.logCardOperation(
    scope: CoroutineScope,
    operationType: String,
    result: String,
    description: String,
    cardNumber: String,
    userId: Long? = null,
    employeeId: String? = null,
    userName: String? = null,
    errorMessage: String? = null,
    detailData: String? = null
) {
    scope.launch(Dispatchers.IO) {
        try {
            val timestamp = System.currentTimeMillis()
            val log = OperationLog(
                operationType = operationType,
                operationSubType = "CARD_SCAN",
                result = result,
                description = description,
                operatorId = userId,
                operatorEmployeeId = employeeId,
                operatorName = userName,
                targetName = "卡号: $cardNumber",
                errorMessage = errorMessage,
                detailData = detailData,
                timestamp = timestamp
            )
            
            // 打印格式化的日志
            printCardOperationLog(operationType, description, cardNumber, userName, result, timestamp)
            
            val repository = OperationLogRepository(applicationContext as android.app.Application)
            repository.insert(log)
            
            Log.d("OperationLogExt", "✅ 刷卡操作日志已保存到数据库")
        } catch (e: Exception) {
            Log.e("OperationLogExt", "❌ 记录刷卡操作日志失败: ${e.message}", e)
        }
    }
}

/**
 * 打印刷卡操作日志到控制台
 */
private fun printCardOperationLog(
    operationType: String,
    description: String,
    cardNumber: String,
    userName: String?,
    result: String,
    timestamp: Long
) {
    val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault())
    val timeStr = dateFormat.format(Date(timestamp))
    
    val operationName = when (operationType) {
        OperationLogConstants.OperationType.INSTRUMENT_TAKE -> "取出"
        OperationLogConstants.OperationType.INSTRUMENT_RETURN -> "归还"
        else -> "刷卡操作"
    }
    
    val resultIcon = if (result == OperationLogConstants.Result.SUCCESS) "✅" else "❌"
    
    val logMessage = buildString {
        appendLine("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
        appendLine(" $resultIcon $operationName 操作日志")
        appendLine("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
        appendLine(" 时间: $timeStr")
        appendLine(" 操作: $operationName")
        appendLine(" 结果: $result")
        appendLine(" 描述: $description")
        appendLine(" 卡号: $cardNumber")
        if (userName != null) {
            appendLine(" 用户: $userName")
        }
        append("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
    }
    
    Log.d("OperationLog", logMessage)
}
